#ifndef ENTITY_FACTORY_H_
#define ENTITY_FACTORY_H_
 
#include "entity.h"
#include "framescene.h"

#include <stdexcept>
#include <map>
#include <algorithm>


class CEntityVec
{
	
private:
	
	std::map< int, CEntity * > m_pEntities;
	std::vector< CEntity * > m_pDrawOrder;
	
public:
	
	~CEntityVec();
	
	void SortDrawOrder();
	
	void RemoveAllEntities();
	
	inline CEntity * GetEntity( int id )
	{
		
		CEntity * e = NULL;
		
		try
		{
			
			e = m_pEntities.at( id );
			
		} catch( std::exception & err ) { }
		
		return e;
		
	}
	
	inline bool RemoveEntity( int id )
	{
		
		CEntity * e = NULL;
		
		for( int j = 0; j < m_pDrawOrder.size(); j++ )
		{
			
			if( m_pDrawOrder[j]->GetUniqueID() == id )
			{
				
				m_pDrawOrder.erase( m_pDrawOrder.begin() + j );
				break;
				
			}
			
		}
		
		try
		{
			
			e = m_pEntities.at( id );
			
			if( e )
			{
				
				m_pEntities.erase( id );
				delete e;
	
				return true;
			}
		
		} catch( std::exception & err ) { }
			
		return false;
		
	}
	
	void AddEntity( CEntity * );
	
	void DrawEntities( CFrameScene * );
	
	void EntityCollidingWithEntities( CEntity * , CCollisionReport & );
	
	void Think();
	

};

class CEntityStateVec
{
	
private:
	
	CFrameScene * m_pFrameScene;
	std::map< std::string, CEntityVec * > m_pEntities;
	std::map< int, CEntity * > m_pMappedEntities;
	
	CEntityInterface * m_pEntityInterface;
	
	std::map< int, CEntity * >::iterator m_IterBegin;
	
public:
	
	void BeginIterate();
	CEntity * IterateNextEntity();
	
	bool EntityCollidingWithEntities( CEntity * , CCollisionReport & );
	
	CEntity * NewEntity();
	CEntity * AddEntity( CEntity * );
	
	void EntitiesThink();
	
	void DrawEntitiesRaw();
	void DrawEntitiesToFrameBuffers();
	
	void RemoveEntity( int );
	void RemoveAllEntities();
	
	CEntity * GetEntity( int );
	
	inline void SetFrameScene( CFrameScene * f ) 
	{
	
		
		m_pFrameScene = f;
		
	}
	
	~CEntityStateVec();
	
	inline void SetEntityInterface( CEntityInterface * intf )
	{
		
		m_pEntityInterface = intf;
		
	}
	
};

class CEntityFactory
{

private:

	CSmartMap< int, CEntityStateVec > m_vEntStateVec;
	
	CFrameScene * m_pFrameScene;
	CEntityInterface * m_pEntityInterface;
	
	int m_CurState;

public:
	
	CEntityFactory() : m_CurState( 0 )
	{  }
	
	inline void SetCurState( int s )
	{
		
		m_CurState = s;
		
	}
	
	~CEntityFactory()
	{
		
		m_vEntStateVec.clear();
		
	}

	inline CEntityStateVec * GetStateVec( int i = -1 )
	{
		
		if( i == -1 )
			i = m_CurState;
		
		CEntityStateVec * v = NULL;
	
		v = m_vEntStateVec.at( i );
			
		if( v == NULL )
		{
		
			v = new CEntityStateVec;
			m_vEntStateVec.set( i, v );
			v->SetFrameScene( m_pFrameScene );
			v->SetEntityInterface( m_pEntityInterface );


		}
		
		return v;
		
	}
	
	inline void SetFrameScene( CFrameScene * f )
	{
		
		m_pFrameScene = f;
		
	}
	
	inline void SetEntityInterface( CEntityInterface * intf )
	{
		
		m_pEntityInterface = intf;
		
	}
	

};

#endif
